package generic;

import java.util.ArrayList;
import java.util.List;

/**
 * @author DCSGO
 * @version 1.0
 * 泛型介绍
 */
public class Generic02 {
    //1)泛型又称参数化类型是 Jdk5.0 出现的新特性 解决数据类型的安全性问题
    //2)在类声明或实例化时只要指定好需要的具体的类型即可
    //3)Java 泛型可以保证如果程序在编译时没有发出警告 运行时就不会产生
    //   ClassCastException 异常 同时代码更加简洁 健壮
    //4)泛型的作用是: 可以在类声明时通过一个标识表示类中某个属性的类型
    //  或者是某个方法的返回值的类型 或者是参数类型
    public static void main(String[] args) {
        Person<String> p1 = new Person<String>("王");
        System.out.println(p1.getName());//王
        //Person<String> p1 = new Person<>("王"); 可理解为:
        /*
         * class Person {
         *     String name;
         *     public Person(String name) {
         *         this.name = name;
         *     }
         *
         *     public String getName() {
         *         return name;
         *     }
         *
         *     ...其他代码
         *
         * }
         * 即将所有的 N 替换为 <> 中的 String
         */

        Person<Integer> p2 = new Person<Integer>(111001);
        System.out.println(p2.getName());//111001

        //Person<Integer> p3 = new Person<Integer>("111001");
        //无法通过编译

        p1.show();//class java.lang.String
        p2.show();//class java.lang.Integer

        //泛型的声明
        //interface 接口<T> 和 class类<K,V>{}
        //比如: List ArrayList
        //public interface List<E> extends Collection<E>
        //public class ArrayList<E> extends AbstractList<E>
        //        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

        //说明:
        //1)其中 T K V 不代表值 而是表示类型
        //2)任意字母都可以 常用 T 表示是 Type 的缩写
        //泛型的实例化:
        //要在类名后面指定类型参数的值(类型) 如:
        //1) List<String> strList = new ArrayList<String>();
        //2) Iterator<Customer> iterator = customers.iterator();
    }
}

class Person<N> {
    N name;//N 表示 name 的数据类型
    //该数据类型在定义 Person 对象的时候指定
    //即在编译期间就确定 N 是什么类型

    public Person(N name) {//N 可以是参数类型
        this.name = name;
    }

    public N getName() {//N 还可以是返回类型
        return name;
    }

    public void show() {
        System.out.println(name.getClass());
    }

    @Override
    public String toString() {
        return "Person{" +
                "name=" + name +
                '}';
    }
}
